package de.fhaugsburg.games.boardgames.commandline;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;




public class CommandScanner {

	private ICommand[] allCommands;
	private BufferedReader in;
	
	
	public CommandScanner(ICommand[] commands) {
		this.allCommands = commands;
		in = new BufferedReader(new InputStreamReader( System.in ) );
	}
	
	
	
	public void setInputstream(Reader newstream){
		in = new BufferedReader(newstream);		
	}
	
	
	/**
	 * reads and parses next command from inputstream
	 * @return
	 * @throws CommandException
	 */
	public ICommand next() throws CommandException{
		ICommand command = null;
		//get user input
//		BufferedReader in = new BufferedReader(new InputStreamReader( System.in ) );

		try {
			String inputLine = in.readLine();

			//entered tokens in one array
			String[] commandTokenString = inputLine.trim().split(" ");
			int commandTokensCount = commandTokenString.length -1; 
			
			
			
			/**
			 * known command entered?
			 */
			for(ICommand commandToken: allCommands) {
				if(commandToken.getToken().compareToIgnoreCase(commandTokenString[0]) == 0) {
					command = commandToken;
					break;
				}
			}
			if (command == null){
				throw new CommandException("unknown command: 'help' to list available commands");
			}	
			
			
			
			//valid command given? lets proceed to the parameters
			if (command != null){
				
				String paramToken = null;
				//returning this array as parameters for our command
				Object[] paramArray = new Object[command.getParamTypes().length];

					
				
					//check all expected parameters
					int i = 0;
					for (Class<?> paramType: command.getParamTypes()){

						//entered enough parameters?
						if (i < commandTokensCount){
							paramToken = commandTokenString[i+1];
							
						//Integer expected
						if (paramType == Integer.class){
							try {
								paramArray[i] = Integer.parseInt(paramToken);
							}catch(NumberFormatException e){
								throw new CommandException("parameter " + i + " has to be numerical");
							}
						}else
						//String expected
						if (paramType == String.class){
							try {
								paramArray[i] = paramToken;
							}catch(Exception e){
								throw new CommandException("parameter " + i + " has to be a string");
							}
						}else 
						//Char expected
						if (paramType == Character.class){
							try {
								paramArray[i] = paramToken.charAt(0);
							}catch(Exception e){
								throw new CommandException("parameter " + i + " has to be a character");
							}
						}else 
						//Float expected
						if (paramType == Float.class){
							try {
								paramArray[i] = Float.parseFloat(paramToken);
							}catch(NumberFormatException e){
								throw new CommandException("parameter " + i + " has to be a float");
							}
						}else
						//type not implemented
						{
							throw new CommandException("unknown parameter type expected, please update your program");
						}
					
						
					}else{
						throw new CommandException("expected " + command.getParamTypes().length + " parameter(s), " + commandTokensCount + " given");
					}
					
					i++;		//next paramToken
				}		//for
				

				//everything fine down here
				command.setParams(paramArray);	
				return command;
			}	//if params
							
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		return null;
	}
	
}
